package io.yx.flx.util;

import org.apache.commons.codec.binary.Hex;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * @author YX
 * @date 2020/3/13 9:51
 */
public class SHAUtil {

    public static final String SHA = "SHA1";
    public static final String SHA_256 = "SHA-256";
    public static final String SHA_384 = "SHA-384";
    public static final String SHA_512 = "SHA-512";


    /**
     * 计算传入数据的SHA1消息摘要
     *
     * @param data 源数据
     * @return SHA1摘要
     * @throws Exception
     */
    public static byte[] encodeSHA(byte[] data) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA");
        return md.digest(data);
    }

    /**
     * 计算传入数据的SHA256消息摘要
     *
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] encodeSHA256(byte[] data) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        return md.digest(data);
    }

    /**
     * 计算传入数据的SHA384消息摘要
     *
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] encodeSHA384(byte[] data) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA-384");
        return md.digest(data);
    }

    /**
     * 计算传入数据的SHA512摘要
     *
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] encodeSHA512(byte[] data) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA-512");
        return md.digest(data);
    }


    /**
     * 计算文本的SHA信息摘要
     *
     * @param dataString
     * @param mdType
     * @return
     * @throws Exception
     */
    public static String messageDigestString(String dataString, String mdType) throws Exception {

        if (dataString == null) {
            throw new RuntimeException("data源数据为空！");
        }
        if (mdType == null) {
            throw new RuntimeException("mdType为空！");
        }

        byte[] data = getBytes(dataString, StandardCharsets.UTF_8);

        byte[] mdResult = null;

        switch (mdType) {
            case SHA:
                mdResult = encodeSHA(data);
                break;
            case SHA_256:
                mdResult = encodeSHA256(data);
                break;
            case SHA_384:
                mdResult = encodeSHA384(data);
                break;
            case SHA_512:
                mdResult = encodeSHA512(data);
                break;
            default:
                throw new RuntimeException("没有找到算法");
        }

        return hexEncode(mdResult);

    }

    /**
     * 将某个字符串以某种字符编码转化为字节数组
     *
     * @param sourceString
     * @param charset
     * @return
     */
    public static byte[] getBytes(String sourceString, Charset charset) {
        return sourceString.getBytes(charset);
    }


    /**
     * byte数组转16进制字符串
     *
     * @param data 字节数组
     * @return 返回16进制字符串
     */
    public static String hexEncode(byte[] data) {

        return Hex.encodeHexString(data);

    }


    /**
     * 计算文件的信息摘要
     *
     * @param file   文件
     * @param mdType 摘要类型
     * @return
     * @throws IOException
     * @throws NoSuchAlgorithmException
     */
    public static String messageDigestFile(File file, String mdType) throws IOException, NoSuchAlgorithmException {

        if (file == null || !file.exists() || !file.isFile()) {
            throw new RuntimeException("文件不存在");
        }

        FileInputStream fileInputStream = new FileInputStream(file);

        DigestInputStream dis = new DigestInputStream(fileInputStream, MessageDigest.getInstance(mdType));

        int read = 0;

        byte[] array = new byte[1024];

        while (read > -1) {
            read = dis.read(array, 0, array.length);
        }

        dis.close();

        MessageDigest md = dis.getMessageDigest();

        byte[] digest = md.digest();

        return hexEncode(digest);

    }

}
